#pragma once

class CThread
{
public:
  CThread(DWORD dwThreadWaitTime = 20000);
  virtual ~CThread();

  virtual bool Run();
  virtual void Stop();

protected:
  template<typename T>
  T SyncGet(const T& var);
  template<typename T>
  void SyncSet(T& var, const T& val);

  void SyncStart()
  { ::EnterCriticalSection(&m_csSync); }
  void SyncStop()
  { ::LeaveCriticalSection(&m_csSync); }

  bool IsTerminating()
  { return SyncGet(m_bTerminate); }

  virtual DWORD ThreadMain() = 0;

private:
  DWORD ThreadMainHndlr();

protected:
  HANDLE   m_hThread;
  DWORD		 m_dwThreadID;
  CRITICAL_SECTION m_csSync;

  bool     m_bTerminate;

  const DWORD m_dwThreadWaitTime;
};

template<typename T>
T CThread::SyncGet(const T& var)
{
  T ret;
  ::EnterCriticalSection(&m_csSync);
  ret = var;
  ::LeaveCriticalSection(&m_csSync);
  return ret;
}

template<typename T>
void CThread::SyncSet(T& var, const T& val)
{
  ::EnterCriticalSection(&m_csSync);
  var = val;
  ::LeaveCriticalSection(&m_csSync);
}
